package org.jparrow.framework.helper;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jparrow.framework.annotation.Aspect;
import org.jparrow.framework.annotation.Controller;
import org.jparrow.framework.proxy.AspectProxy;
import org.jparrow.framework.proxy.Proxy;
import org.jparrow.framework.proxy.ProxyManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 加载AOP框架
 * 
 * @author supda
 * @Date 2017-3-29 上午10:33:08
 *
 */
public final class AOPHelper {

	private static final Logger LOGGER= 
			LoggerFactory.getLogger(AOPHelper.class);
	
	static{
		try{
			//加载所有的AspectProxy代理类子类---@Aspect(@annonation)中@annonation为其映射value
			Map<Class<?>, Set<Class<?>>> proxyMap = createProxyMap();
			LOGGER.debug("代理类与被代理类映射proxyMap:"+proxyMap);
			//被代理类--代理类实例
			Map<Class<?>, List<Proxy>> targetMap = createTargetMap(proxyMap);
			LOGGER.debug("被代理类与代理类实例映射targetMap:"+targetMap);
			
			for(Map.Entry<Class<?>, List<Proxy>> targetEntry : targetMap.entrySet())
			{
				Class<?> targetClass = targetEntry.getKey();
				List<Proxy> proxyList = targetEntry.getValue();
				//目标类，代理实例集合（一个类可能被多个类代理）
				Object proxy = ProxyManager.createProxy(targetClass, proxyList);
				//目标类，代理类（代理类实例作为Bean实例调用）
				BeanHelper.setBean(targetClass, proxy);
			}
			
		}catch(Exception e){
			LOGGER.error("aop failure", e);
		}
	}
	
	/**
	 * 获取Aspect注解中设置的注解类
	 */
	@SuppressWarnings("unused")
	private static Set<Class<?>> createTargetClassSet(Aspect aspect)
		throws Exception {
		Set<Class<?>> targetClassSet = new HashSet<Class<?>>();
		Class<? extends Annotation> annotation = aspect.value();
		
		LOGGER.debug("获取注解为:"+annotation.getName()+" 的类");
		
		if(annotation != null && !annotation.equals(Aspect.class)) {
			targetClassSet.addAll(
					ClassHelper.getClassSetByAnnotation(annotation));
		}
		
		LOGGER.debug("集合为："+targetClassSet);
		return targetClassSet;
	}
	
	//一个代理类可能会存在多个目标类
	@SuppressWarnings("unused")
	private static Map<Class<?>, Set<Class<?>>> createProxyMap() 
		throws Exception{
		Map<Class<?>, Set<Class<?>>> proxyMap = 
				new HashMap<Class<?>, Set<Class<?>>>();
		Set<Class<?>> proxyClassSet = //加载AspectProxy类的所有子类，或实现类
				ClassHelper.getClassSetBySuper(AspectProxy.class);
		for(Class<?> proxyClass : proxyClassSet) {
			//有Aspect注解
			if(proxyClass.isAnnotationPresent(Aspect.class)) {
				Aspect aspect = proxyClass.getAnnotation(Aspect.class);
				Set<Class<?>> targetClassSet = createTargetClassSet(aspect);
				proxyMap.put(proxyClass, targetClassSet);
			}
		}
		return proxyMap;
	}
	
	private static Map<Class<?>, List<Proxy>> createTargetMap(
			Map<Class<?>,Set<Class<?>>> proxyMap) throws Exception{
		Map<Class<?>, List<Proxy>> targetMap = new HashMap<Class<?>,
				List<Proxy>>();
		for(Map.Entry<Class<?>, Set<Class<?>>> proxyEntry : proxyMap.entrySet()){
			//代理类
			Class<?> proxyClass = proxyEntry.getKey();
			//被代理的类
			Set<Class<?>> targetClassSet = proxyEntry.getValue();
			for(Class<?> targetClass : targetClassSet) {
				//代理类实例
				Proxy proxy = (Proxy) proxyClass.newInstance();
				if(targetMap.containsKey(targetClass)) {
					targetMap.get(targetClass).add(proxy);
				}else{
					List<Proxy> proxyList = new ArrayList<Proxy>();
					proxyList.add(proxy);
					targetMap.put(targetClass, proxyList);
				}
			}
		}
		return targetMap;
	}
	
}
